home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / GW AdaEd 1.4.2 / GWAdaDemos / NYUDemos / CLI.ADA next >
Text File  |  1994-01-09  |  11KB  |  297 lines

  1. -- **************************************
  2. -- *                                    *
  3. -- * CLI (Command Line Interface)       * SPEC
  4. -- *                                    *
  5. -- **************************************
  6. package CLI is
  7.  
  8. --| Purpose
  9. --|   CLI is a package which implements a Command
  10. --| Line Interface.  It mirrors the UNIX/C
  11. --| command line interface, providing an argument
  12. --| count and the arguments themselves.
  13. --|
  14. --| Initialization Exceptions (none)
  15. --|
  16. --| Notes
  17. --|   Compiler limit on string length and dynamic memory.
  18. --|   INITIALIZE must be called once, and only once, during
  19. --| the execution of the main Ada proc.
  20. --|
  21. --| Modifications
  22. --|  2/25/88  Richard Conn    Initial Version
  23. --|  5/12/89  Richard Conn    Review and Upgrade
  24. --|  4/11/90  Richard Conn    MIL-HDBK-1804 Annotations and
  25. --|                           Meridian Ada Interface Added
  26.    
  27.   -- ...................................
  28.   -- .                                 .
  29.   -- . CLI.INITIALIZE                  . SPEC
  30.   -- .                                 .
  31.   -- ...................................
  32.   procedure Initialize (Program_Name        : in STRING;
  33.                         Command_Line_Prompt : in STRING);
  34.   --| Purpose
  35.   --|   Initialize this package.  This routine must be called
  36.   --| before any other routines or objects are called or referenced.
  37.   --|
  38.   --| Exceptions (none)
  39.   --|
  40.   --| Notes
  41.   --|   CALL THIS PROCEDURE ONLY ONE TIME
  42.  
  43.   -- ...................................
  44.   -- .                                 .
  45.   -- . CLI.ARGC (Argument Count)       . SPEC
  46.   -- .                                 .
  47.   -- ...................................
  48.   function ArgC return NATURAL;
  49.   --| Purpose
  50.   --|   Return the number (1 to N) of command line arguments.
  51.   --| ARGC is at least 1 because the name of the program or
  52.   --| process is always ARGV(0).
  53.   --|
  54.   --| Exceptions (none)
  55.   --| Notes (none)
  56.  
  57.   -- ...................................
  58.   -- .                                 .
  59.   -- . CLI.ARGV (Argument Value)       . SPEC
  60.   -- .                                 .
  61.   -- ...................................
  62.   function ArgV (Index : in NATURAL) return STRING;
  63.   --| Purpose
  64.   --|   Return the INDEXth (0 <= INDEX < ARGC) command line
  65.   --| argument.  Example: if ARGC = 1, ARGV(0) is the only
  66.   --| valid argument string.  ARGV(0) is always the name of
  67.   --| the program or process.
  68.   --|
  69.   --| Exceptions
  70.   --|   INVALID_INDEX     raised if Index >= ARGC
  71.   --|
  72.   --| Notes (none)
  73.  
  74.   INVALID_INDEX    : exception;
  75.   UNEXPECTED_ERROR : exception;  -- raised anytime
  76.    
  77. end CLI;
  78. -- This implementation of Package Body CLI is general-purpose.
  79. -- Using TEXT_IO, it prompts the user for input arguments and
  80. -- accepts these arguments via a GET_LINE call.
  81. with TEXT_IO;
  82. package body CLI is
  83.  
  84.    LOCAL_ARGC : NATURAL := 0;
  85.    
  86.    package STRING_LIST is
  87.       
  88.       NUMBER_OF_STRINGS : NATURAL := 0;
  89.       
  90.       procedure ADD_TO_LIST (ITEM : in STRING);
  91.       function GET_FROM_LIST (ITEM : in NATURAL) return STRING;
  92.       
  93.    end STRING_LIST;
  94.    
  95.    package body STRING_LIST is
  96.       
  97.       type DYNAMIC_STRING_OBJECT (LENGTH : NATURAL);
  98.       type DYNAMIC_STRING is access DYNAMIC_STRING_OBJECT;
  99.       type DYNAMIC_STRING_OBJECT (LENGTH : NATURAL) is 
  100.          record
  101.             DS   : STRING (1 .. LENGTH);
  102.             NEXT : DYNAMIC_STRING;
  103.          end record;
  104.       
  105.       FIRST : DYNAMIC_STRING := null;
  106.       LAST  : DYNAMIC_STRING := null;
  107.       
  108.       procedure ADD_TO_LIST (ITEM : in STRING) is
  109.          
  110.          --========================= PDL ===========================
  111.          --|ABSTRACT:
  112.          --|    ADD_TO_LIST adds the ITEM string to the linked list
  113.          --|    of dynamic strings implemented by this package.
  114.          --|DESIGN DESCRIPTION:
  115.          --|    Create new DYNAMIC_STRING_OBJECT of the proper length
  116.          --|    Set DS field of new object to the ITEM string
  117.          --|    Set the NEXT field of the new object to NULL
  118.          --|    If FIRST pointer is null
  119.          --|      Set FIRST and LAST to point to the new object
  120.          --|    Else
  121.          --|      Set LAST.NEXT to point to the new object
  122.          --|      Set LAST to point to the new object
  123.          --|    End if
  124.          --|    Increment NUMBER_OF_STRINGS
  125.          --=========================================================
  126.          
  127.          TEMP : DYNAMIC_STRING;
  128.       begin
  129.          TEMP := new DYNAMIC_STRING_OBJECT (ITEM'LENGTH);
  130.          TEMP.DS (1 .. ITEM'LENGTH) := ITEM;
  131.          TEMP.NEXT                  := null;
  132.          if FIRST = null then
  133.             FIRST := TEMP;
  134.             LAST  := TEMP;
  135.          else
  136.             LAST.NEXT := TEMP;
  137.             LAST      := TEMP;
  138.          end if;
  139.          NUMBER_OF_STRINGS := NUMBER_OF_STRINGS + 1;
  140.       end ADD_TO_LIST;
  141.       
  142.       function GET_FROM_LIST (ITEM : in NATURAL) return STRING is
  143.          
  144.          --========================= PDL ===========================
  145.          --|ABSTRACT:
  146.          --|    GET_FROM_LIST returns the ITEM string from the linked list
  147.          --|    of dynamic strings implemented by this package.
  148.          --|DESIGN DESCRIPTION:
  149.          --|    If ITEM > 0
  150.          --|        Advance to desired item
  151.          --|    End If
  152.          --|    Return the DS field of the desired item
  153.          --=========================================================
  154.          
  155.          ROVER : DYNAMIC_STRING := FIRST;
  156.       begin
  157.          if ITEM > 0 then
  158.             for I in 1 .. ITEM loop
  159.                ROVER := ROVER.NEXT;
  160.             end loop;
  161.          end if;
  162.          return ROVER.DS;
  163.       end GET_FROM_LIST;
  164.       
  165.    end STRING_LIST;
  166.    
  167.    procedure INITIALIZE (PROGRAM_NAME        : in STRING;
  168.                          COMMAND_LINE_PROMPT : in STRING) is
  169.       
  170.       --========================= PDL ===========================
  171.       --|ABSTRACT:
  172.       --|    INITIALIZE prompts the user for the command line
  173.       --|    arguments and loads the linked list with them.
  174.       --|DESIGN DESCRIPTION:
  175.       --|    Set CURRENT_STATE to LOOKING_FOR_TOKEN
  176.       --|    Set the first list object to PROGRAM_NAME
  177.       --|    Prompt the user with COMMAND_LINE_PROMPT and
  178.       --|      get his response
  179.       --|    Over number of characters in line, loop
  180.       --|        Case CURRENT_STATE
  181.       --|            When LOOKING_FOR_TOKEN
  182.       --|                If character is not white-space
  183.       --|                    Set CURRENT_STATE to IN_TOKEN
  184.       --|                    If character is quote (")
  185.       --|                        Set QUOTED to TRUE
  186.       --|                        Set START to the character's index + 1
  187.       --|                    Else
  188.       --|                        Set QUOTED to FALSE
  189.       --|                        Set START to the character's index
  190.       --|                    End IF
  191.       --|                End If
  192.       --|            When IN_TOKEN
  193.       --|                If QUOTED
  194.       --|                    If character is quote (")
  195.       --|                        Set STOP to the previous character's index
  196.       --|                        Add slice from START to STOP to list
  197.       --|                        Set CURRENT_STATE to LOOKING_FOR_TOKEN
  198.       --|                    End If
  199.       --|                ElsIF character is white-space
  200.       --|                    Set STOP to the previous character's index
  201.       --|                    Add slice from START to STOP to list
  202.       --|                    Set CURRENT_STATE to LOOKING_FOR_TOKEN
  203.       --|                End If
  204.       --|        End Case
  205.       --|    End Loop
  206.       --|    If CURRENT_STATE is IN_TOKEN
  207.       --|        Set STOP to the previous character's index
  208.       --|        Add slice from START to STOP to list
  209.       --|    End if
  210.       --|    Set LOCAL_ARGC to NUMBER_OF_STRINGS
  211.       --|    Output NEW_LINE (to reset column count in TEXT_IO)
  212.       --=========================================================
  213.       
  214.       ARGCOUNT      : NATURAL := 1;
  215.       INLINE        : STRING (1 .. 400);
  216.       LAST          : NATURAL;
  217.       START         : NATURAL;
  218.       STOP          : NATURAL;
  219.       QUOTED        : BOOLEAN;
  220.       type STATE is (LOOKING_FOR_TOKEN, IN_TOKEN);
  221.       CURRENT_STATE : STATE   := LOOKING_FOR_TOKEN;
  222.    begin
  223.       STRING_LIST.ADD_TO_LIST (PROGRAM_NAME);
  224.       TEXT_IO.PUT (COMMAND_LINE_PROMPT);
  225.       TEXT_IO.GET_LINE (INLINE, LAST);
  226.       for I in 1 .. LAST loop
  227.          case CURRENT_STATE is
  228.             when LOOKING_FOR_TOKEN  =>
  229.                if INLINE (I) > ' ' then
  230.                   CURRENT_STATE := IN_TOKEN;
  231.                   if INLINE (I) = '"' then
  232.                      QUOTED := TRUE;
  233.                      START  := I;
  234.                   else
  235.                      QUOTED := FALSE;
  236.                      START  := I;
  237.                   end if;
  238.                end if;
  239.             when IN_TOKEN =>
  240.                if QUOTED then
  241.                   if INLINE (I) = '"' then
  242.                      STOP          := I;
  243.                      STRING_LIST.ADD_TO_LIST (INLINE (START .. STOP));
  244.                      CURRENT_STATE := LOOKING_FOR_TOKEN;
  245.                   end if;
  246.                elsif INLINE (I) <= ' ' then
  247.                   STOP          := I - 1;
  248.                   STRING_LIST.ADD_TO_LIST (INLINE (START .. STOP));
  249.                   CURRENT_STATE := LOOKING_FOR_TOKEN;
  250.                end if;
  251.          end case;
  252.       end loop;
  253.       if CURRENT_STATE = IN_TOKEN then
  254.          STOP := LAST;
  255.          STRING_LIST.ADD_TO_LIST (INLINE (START .. STOP));
  256.       end if;
  257.       LOCAL_ARGC := STRING_LIST.NUMBER_OF_STRINGS;
  258.       TEXT_IO.NEW_LINE;
  259.    end INITIALIZE;
  260.    
  261.    function ARGC return NATURAL is
  262.       
  263.       --========================= PDL ===========================
  264.       --|ABSTRACT:
  265.       --|    ARGC returns the argument count.
  266.       --|DESIGN DESCRIPTION:
  267.       --|    Return LOCAL_ARGC
  268.       --=========================================================
  269.       
  270.    begin
  271.       return LOCAL_ARGC;
  272.    end ARGC;
  273.  
  274.    function ARGV (INDEX : in NATURAL) return STRING is
  275.       
  276.       --========================= PDL ===========================
  277.       --|ABSTRACT:
  278.       --|    ARGV returns the indicated argument string.
  279.       --|DESIGN DESCRIPTION:
  280.       --|    If INDEX is out of range, raise INVALID_INDEX
  281.       --|    Return GET_FROM_LIST(INDEX)
  282.       --=========================================================
  283.       
  284.    begin
  285.       if INDEX >= LOCAL_ARGC then
  286.          raise INVALID_INDEX;
  287.       end if;
  288.       return STRING_LIST.GET_FROM_LIST (INDEX);
  289.    exception
  290.       when INVALID_INDEX  =>
  291.          raise ;
  292.       when others    =>
  293.          raise UNEXPECTED_ERROR;
  294.    end ARGV;
  295.    
  296. end CLI;
  297.